We have discovered that the C language lets us express values we want to keep track of as variables. These can be regarded as boxes with names. However, the compiler which we are using has set up a number of special "variables" which map on to ports or registers of the PIC microprocessor. As you will see from the PIC reference library, these ports are how we drive the PIC hardware, make it read and write signals from the outside world and set up various configuration options.
The compiler actually does this by using a non-standard special trick. It is possible to tell the compiler to make a particular variable live at a particular location in memory. Normally the compiler will automatically choose a place for a variable, but if we happen to know that a particular PIC port lives at a particular address we can place a variable there. This works because the PIC uses a technique called memory mapping for its ports. In other words, particular memory locations are specially reserved for use by the hardware. Normally we don't put variables in these positions because the effect would be to make the hardware do very silly things when our program runs. However, the compiler lets you add information to a variable declaration to force it to be stored by the compiler in a particular place:
char PORTA@0x0005;
This looks very like a normal declaration of a character variable called PORTA, except for the @0x0005 bit on the end. The 0x0005 is the address in hex of this port in the PIC memory space. This means that a line of code like:
PORTA = 0x00;
- would have the effect of putting the value 0 into memory location number 0x0005, which is where PORTA lives. Note that we are using the char type for these values, which means that the ports are 8 bits wide.
These settings are given in a special include file which can be added to the top of every program that you write. The upshot is that if we want to put a value into one of the PIC ports we can use that port as we would any other register. On the right is a list of the ports variables which have been set up for the 16F88 processor.
To find out what each port does you can refer to the PIC documentation or the PIC section of this course.
Actually there is something even stranger going in when you use these constants. Some of the hardware ports are held in different PIC banks. (the PIC uses a number of these to save on address space). This means that when the compiler uses these values it actually drops out other instructions to make sure that the bank mapping makes sense for the register that you are usihg. You can find out more about banks in the PIC reference; for now just take it on trust that this happens and works correctly!
These are the special port addresses for the PIC16F84 processor. You can use them by issuing an include statement:
#include <system.h>
- at the beginning of your program.
char INDF@0x0000;
char TMR0@0x0001;
char PCL@0x0002;
char STATUS@0x0003;
char FSR@0x0004;
char PORTA@0x0005;
char PORTB@0x0006;
char PCLATH@0x000A;
char INTCON@0x000B;
char PIR1@0x000C;
char PIR2@0x000D;
char TMR1L@0x000E;
char TMR1H@0x000F;
char T1CON@0x0010;
char TMR2@0x0011;
char T2CON@0x0012;
char SSPBUF@0x0013;
char SSPCON@0x0014;
char CCPR1L@0x0015;
char CCPR1H@0x0016;
char CCP1CON@0x0017;
char RCSTA@0x0018;
char TXREG@0x0019;
char RCREG@0x001A;
char ADRESH@0x001E;
char ADCON0@0x001F;
char OPTION_REG@0x0081;
char TRISA@0x0085;
char TRISB@0x0086;
char PIE1@0x008C;
char PIE2@0x008D;
char PCON@0x008E;
char OSCCON@0x008F;
char OSCTUNE@0x0090;
char PR2@0x0092;
char SSPADD@0x0093;
char SSPSTAT@0x0094;
char TXSTA@0x0098;
char SPBRG@0x0099;
char ANSELA@0x009B;
char CMCON@0x009C;
char CVRCON@0x009D;
char ADRESl@0x009E;
char ADCON1@0x009F;
char WDTCON@0x0105;
char EEDATA@0x010C;
char EEADR@0x010D;
char EEDATH@0x010E;
char EEADRH@0x010F;
char EECON1@0x018C;
char EECON2@0x018D;